package see.battle.adaptor;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OptionalDataException;
import java.util.LinkedList;

import android.bluetooth.BluetoothSocket;

import see.battle.Const;
import see.battle.gui.Game.ResultProcessor;
import see.battle.message.BulletMessage;
import see.battle.message.InitializeMessage;
import see.battle.message.Message;
import see.battle.message.OpponentFocusMessage;

public class GlobalAdaptor implements Adaptor {
  private Message _m;  
  private boolean _stop = false;
  private int _view;
  private LinkedList<Message> _messages = new LinkedList<Message>();
  private ObjectInputStream _input;
  private ObjectOutputStream _output;
  private long _t1 = 0;
  private long _t2 = 0;
  private long _diff = 0;
  private ResultProcessor _resultProcessor;

  public void set_resultProcessor(ResultProcessor resultProcessor) {
    _resultProcessor = resultProcessor;
  }

  @SuppressWarnings("static-access")
  public GlobalAdaptor(BluetoothSocket bs) throws IOException {
    try {
      Thread.currentThread().sleep(1000);
    } catch (InterruptedException e) {
      e.printStackTrace();
    }
    System.err.println("global adaptor constructor begin");
    _input = new ObjectInputStream(bs.getInputStream());
    System.err.println("global adaptor input ok");
    _output = new ObjectOutputStream(bs.getOutputStream());
    _output.flush();
    System.err.println("global adaptor output ok");
  }

  public void set_view(int view) {
	_view = view;  
  }
  
  private void initGame() {
    try {
      _t1 = System.currentTimeMillis();
      _output.writeObject(new InitializeMessage(_t1));
      _output.flush();
    } catch (IOException e) {
      e.printStackTrace();
    }
  }
  
  private void calcDiff(InitializeMessage m, long t3) {
    _t2 = m.get_time();
    _diff = _t1 - (_t2 - (t3 - _t1) / 2);
    System.err.print("GA difference");
    System.err.println(_diff);
  }
  
  private void closeActivity() {
    try {
      _resultProcessor.call();
    } catch (Exception e1) {
      e1.printStackTrace();
    }
  }
  
  public void run() {
    initGame();
    System.err.println("GA init is sent");
    while (true) {
      if (_stop) break;
      Message m = null;
        try {
          m = (Message)_input.readObject();
        } catch (OptionalDataException e) {
          e.printStackTrace();
        } catch (ClassNotFoundException e) {
          e.printStackTrace();
        } catch (IOException e) {
          e.printStackTrace();
        }
      if (m != null) {
        if (m.type() != Const.initializeMessageType) {
          synchronized (_messages) {
            m.updateTime(_diff);
            _messages.add(m); 
          }
        } else {
          System.err.println("Adaptor Message about init is received");
          calcDiff((InitializeMessage) m, System.currentTimeMillis());
       }
      }
    }
  }

  public void stop() {
    _stop = true;
  }

  public Message readNextMessage() {
    _m = null;
    synchronized (_messages) {
      if (_messages.size() != 0) {
        _m = _messages.getFirst();
        _messages.removeFirst();
      }
    }
    return _m;
  }

  //@Override
  public void sendBulletMessage(long time, float position, 
      long additionalShipDelay) {
    try {
      if (_diff != 0) {
        time -= _diff;
        System.err.print("bullet message from user at ");
        System.err.println(time);
        _output.writeObject(new BulletMessage(time, position, 
            additionalShipDelay, _view));
        _output.flush();
      }
    } catch (IOException e) {
      e.printStackTrace();
    }
  }

  //@Override
  public void sendFocusMessage(float focus) {
    try {
      if (_diff != 0) {
        _output.writeObject(new OpponentFocusMessage(focus));
        _output.flush();
      }
    } catch (IOException e) {
      e.printStackTrace();
    }
  }
}
